const defaults = {
	timeout: 0// 超时的时间
}

// Axios类
class Axios {
	constructor(instanceConfig) {
		// 默认配置项
		this.defaults = instanceConfig;
	}
	
	// configOrUrl:配置对象或地址
	// config:地址
	request(configOrUrl, config) {
		// 判断参数configOrUrl是否为字符串
		if (typeof configOrUrl === "string") {
			// 将接收到的参数config,作为配置项，如果config为undefined,默认为{}
			config = config || {};
			// 将配置对象中的url属性值设置为configOrUrl
			config.url = configOrUrl;
		} else {
			// 将configOrUrl作为配置对象，如果configOrUrl为undefined,默认为{}
			config = configOrUrl || {};
		}
		// 将默认配置项this.defaults,与config进行合并
		config = {
			...this.defaults,
			...config
		}
		// 设置默认请求方式
		config.method = (config.method || this.defaults.method || "get").toLowerCase();
		
		// 设置config.url
		if (config.baseURL && !config.url.startsWith("http://")) {
			config.url = config.baseURL + config.url;
		}
		
		
		// 发送请求
		const dispatchRequest = function () {
			return new Promise((resolve, reject) => {
				const request = new XMLHttpRequest();
				request.timeout = config.timeout;
				request.responseType = "json";
				if (config.cancelToken) {
					config.cancelToken.cancel.then(value => {
						request.abort();// 取消请求
					})
				}
				request.open(config.method, config.url);
				request.send();
				request.onload = function () {
					resolve({
						// axios配置对象
						config,
						// 响应体
						data: request.response,
						// 响应头
						headers: request.getAllResponseHeaders(),
						// XMLHttpRequest实例
						request,
						status: request.status,
						statusText: request.statusText
					})
				}
				// 超时
				request.ontimeout = function (err) {
					reject({
						config,
						message: "timeout of " + config.timeout + "ms exceeded",
						code: "ECONNABORTED",
						name: "AxiosError",
						request,
						stack: err
					})
				}
				// 取消请求回调
				request.onabort = function () {
					reject({
						code: "ERR_CANCELED",
						message: "canceled",
						name: "CanceledError"
					})
				}
			})
			
		}
		return dispatchRequest.call(this);
	}
}


// createInstance返回实例（使用的axios)
function createInstance(defaultConfig) {
	const context = new Axios(defaultConfig);
	// 将Axios实例绑定到Axios.prototype.request
	const instance = Axios.prototype.request.bind(context);
	for (let key in context) {
		instance[key] = context[key];
	}
	return instance;
}

const axios = createInstance(defaults);
axios.CancelToken = function (cb) {
	this.cancel = new Promise(resolve => {
		cb(resolve);
	})
}
axios.isCancel = function(err){
	return err.name === "CanceledError"
}
axios.all = function(promises){
	return Promise.all(promises);
}
export default axios;